/*
 * FindBugs - Find Bugs in Java programs
 * Copyright (C) 2003-2008 University of Maryland
 * 
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 * 
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

package edu.umd.cs.findbugs.gui2;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;

import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTabbedPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.JTableHeader;

import edu.strath.cis.grallan.findbugs.adaptiveranking.gui.AdaptiveRankingPanelProvider;
import edu.umd.cs.findbugs.Project;
import edu.umd.cs.findbugs.gui2.IApplicationState.UIFactory;
import edu.umd.cs.findbugs.gui2.sort.SortableBugTree;
import edu.umd.cs.findbugs.gui2.sort.SorterTableColumnModel;
import edu.umd.cs.findbugs.gui2.sort.SorterTableHeader;

/**
 * 
 * @author Graham Allan (grallan@cis.strath.ac.uk)
 */
public class BugListPanelProvider implements IViewController {

	private JPanel treePanel;
	private JScrollPane treeScrollPane;
	private JTextField textFieldForPackagesToDisplay;
	private ShowHidePanel cardPanel;
	private SorterTableHeader tableheader;
	private SortableBugTree tree;
	private BugTreePopupProvider popupProvider;

	private List<ShowHidePanel> treePanels = new ArrayList<ShowHidePanel>();
	private final MainFrame mainFrame;

	private BugSelectionListener bugSelectionState;
	private SorterTableColumnModel sorter;
	private final IApplicationState applicationState;
	private final UIFactory uiFactory;

	public BugListPanelProvider(MainFrame mainFrame, IApplicationState applicationState,
			BugSelectionListener bugSelectionState, UIFactory uiFactory) {
		this.mainFrame = mainFrame;
		this.applicationState = applicationState;
		this.bugSelectionState = bugSelectionState;
		this.uiFactory = uiFactory;

	}

	public JPanel bugListPanel() {

		popupProvider = BugTreePopupProvider.popupProviderPrototype(applicationState, uiFactory, mainFrame);

		tree = new SortableBugTree(mainFrame, popupProvider);
		tableheader = makeSorterTableHeader(tree);

		BugTreeModel bugTreeModel = new CachedBugTreeModel(tree, sorter, new BugSet(new ArrayList<BugLeafNode>(),
				mainFrame), uiFactory.filterActivity());
		bugTreeModel.setTreeHolder(mainFrame);
		tree.setModel(bugTreeModel);
		tree.addBugSelectionListener(bugSelectionState);

		mainFrame.setProject(new Project());

		treeScrollPane = new JScrollPane(tree);

		treePanel = new JPanel(new BorderLayout());
		treePanel.add(treeScrollPane, BorderLayout.CENTER);
		// New code to fix problem in Windows
		JTable t = new JTable(new DefaultTableModel(0, mainFrame.sortables().size()));
		t.setTableHeader(tableheader);

		// End of new code.
		// Changed code.
		textFieldForPackagesToDisplay = new JTextField();
		textFieldForPackagesToDisplay.addActionListener(new ActionListener() {

			public void actionPerformed(ActionEvent e) {
				try {
					mainFrame.viewFilter.setPackagesToDisplay(textFieldForPackagesToDisplay.getText());
					mainFrame.resetViewCache();
				} catch (IllegalArgumentException err) {
					JOptionPane.showMessageDialog(mainFrame, err.getMessage(), "Bad class search string",
							JOptionPane.ERROR_MESSAGE);
				}
			}
		});

		textFieldForPackagesToDisplay
				.setToolTipText("Provide a comma separated list of class search strings to restrict the view to classes containing those substrings");
		JPanel topPanel = makeNavigationPanel("Class search strings:", textFieldForPackagesToDisplay, tableheader,
				treePanel);

		cardPanel = new ShowHidePanel(mainFrame);

		JTabbedPane tabbedPane = new JTabbedPane();
		tabbedPane.add("Bug List", topPanel);
		tabbedPane.add("FindBugs Training", makeAdaptiveRankingPanel());

		JPanel tabbedPanel = new JPanel(new BorderLayout());
		tabbedPanel.add(tabbedPane, BorderLayout.CENTER);

		cardPanel.setTreePanel(tabbedPanel);
		cardPanel.showView();

		treePanels.add(cardPanel);

		return cardPanel;
	}

	private JPanel makeAdaptiveRankingPanel() {
		return new AdaptiveRankingPanelProvider().makeAdaptiveRankingPanel(applicationState,
				mainFrame.comments, popupProvider, mainFrame, bugSelectionState, cardPanel);
	}

	private SorterTableHeader makeSorterTableHeader(SortableBugTree treeForSorterTable) {
		sorter = GUISaveState.getInstance().getStarterTable();
		SorterTableHeader newTableheader = new SorterTableHeader(sorter);
		// Listener put here for when user double clicks on sorting
		// column header SorterDialog appears.
		newTableheader.addSorterMouseListener(treeForSorterTable);
		return newTableheader;
	}

	public void newTree(final SortableBugTree newTree, final BugTreeModel newModel) {

		class NewTreeRunnable implements Runnable {
			public void run() {
				updateSortListeners(tree, newTree);

				tree = newTree;

				newModel.setTreeHolder(mainFrame);

				treePanel.remove(treeScrollPane);
				treeScrollPane = new JScrollPane(tree);
				treePanel.add(treeScrollPane);
				mainFrame.setFontSizeHelper(Driver.getFontSize(), treeScrollPane);

				mainFrame.getContentPane().validate();
				mainFrame.getContentPane().repaint();

				newModel.openPreviouslySelected(((BugTreeModel) (tree.getModel())).getOldSelectedBugs());
				tree.expandTree(10);
				tree.expandToFirstLeaf(14);
				getSorter().addColumnModelListener(newModel);
				uiFactory.filterActivity().addFilterListener(newModel.bugTreeFilterListener);
				tableHeader().setReorderingAllowed(true);

				showTreeCard();

			}
		}

		SwingUtilities.invokeLater(new NewTreeRunnable());
	}

	public SorterTableColumnModel getSorter() {
		return sorter;
	}

	JPanel makeNavigationPanel(String packageSelectorLabel, JComponent packageSelector, JComponent treeHeader,
			JComponent treePanel) {
		JPanel topPanel = new JPanel();
		topPanel.setMinimumSize(new Dimension(150, 150));

		topPanel.setLayout(new GridBagLayout());
		GridBagConstraints c = new GridBagConstraints();
		c.ipadx = c.ipady = 3;
		c.insets = new Insets(6, 6, 6, 6);
		c.gridx = 0;
		c.gridy = 0;
		c.fill = GridBagConstraints.NONE;
		JLabel label = new JLabel(packageSelectorLabel);
		topPanel.add(label, c);

		c.gridx = 1;
		c.fill = GridBagConstraints.HORIZONTAL;
		c.weightx = 1;
		topPanel.add(packageSelector, c);

		c.gridx = 0;
		c.gridwidth = 2;
		c.gridy++;
		c.ipadx = c.ipady = 2;
		c.fill = GridBagConstraints.HORIZONTAL;
		topPanel.add(treeHeader, c);

		c.fill = GridBagConstraints.BOTH;
		c.gridy++;
		c.weighty = 1;
		c.ipadx = c.ipady = 0;
		c.insets = new Insets(0, 0, 0, 0);
		topPanel.add(treePanel, c);
		return topPanel;
	}

	public void setPackagesToDisplay(String filter) {
		textFieldForPackagesToDisplay.setText(filter);
	}

	public void hideView() {
		showWaitCard();
	}

	public void showView() {
		showTreeCard();
	}

	public void showWaitCard() {
		for (ShowHidePanel treePanel : treePanels) {
			treePanel.hideView();
		}
	}

	public void showTreeCard() {
		for (ShowHidePanel treePanel : treePanels) {
			treePanel.showView();
		}
	}

	public SortableBugTree getTree() {
		return tree;
	}

	public void setPopupMenuFonts(float size) {
		popupProvider.setPopupMenuFonts(size);
	}

	public JTableHeader tableHeader() {
		return tableheader;
	}

	private void updateSortListeners(SortableBugTree oldTree, SortableBugTree newTree) {
		tableheader.removeSorterMouseListener(oldTree);
		tableheader.addSorterMouseListener(newTree);
	}

}
